使用一元运算符多次管道
Piping multilpe times using unary operator
我有以下功能:
Function Refine{
[CmdletBinding()]
param (
[parameter(ValueFromPipeline = $true)]
$data
)
begin {}
process {
For ($i=0; $i -le $data.count; $i++){
if ($data[$i] -match 'nmap scan report' -and $data[$i+1] -match 'host is up' ) {
$dat += $data[$i] + "`n"
$counter=($i+4)
while ($data[$counter] -match '^[0-9]') {
$dat += $data[$counter] + "`n"
$counter++
}
}
}
}
end {
if ($dat){#See that its not empty
return $dat.Split([Environment]::NewLine)
}
}
}
$file1 = gc c:\test.txt
,gc ($file1) | Refine
我必须使用一元运算符进行管道传输,因为我希望将整个对象一次性传输到优化函数。
例如,输出是这样的:
1.1.1.1 的 Nmap 扫描报告
113/tcp 关闭标识
443/tcp 打开 ssl/http Fortinet SSL VPN
2.2.2.2 的 Nmap 扫描报告
21/tcp 过滤 ftp
22/tcp 过滤 ssh
我现在想使用另一个函数,它接受这个并从文本创建对象:
Function BuildArray{
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]
$data
)
Begin {}
Process {
$NMAPS=@()
$nmap=@()
$ports=@()
For ($i=0; $i -lt $data.count; $i++){
If ($data[$i] -match 'nmap scan report') {
$ip = ($data[$i] | Select-String -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.Value
$k=$i
If ($data[($i+1)] -notmatch 'nmap scan report' -and $i -le $data.count){
DO{
$ports+=$data[$i+1]
$i++
}
While ($data[$i+1] -notmatch 'nmap scan report' -and $i -le $data.count)
$nmap = @{IP = "$ip"; ports=@($ports)}
$NMAPS+=$nmap
$nmap=@()
$ports=@()
$i = $k
}
}
}
}
End {
$NMAPS
}
}
我的问题又来了——我希望管道中的数据作为一个整体传递给 BuildArray 函数。但我不能使用一元运算符,因为我收到一条错误消息,说我只能在管道的开头使用它,
,(gc $file1 ) | ,(refine) | BuildArray #No good
如何将管道中的第二个对象作为一个整体一次性传递给第三个对象?
恕我直言,您对 PowerShell pipeline. Cmdlets should implement for the Middle of a Pipeline 的一般概念并不正确,这意味着每个 cmdlet 都应该处理每个项目 a.s.a.p。 将其流到下一个cmdlet,最终将其从内存中释放。
PowerShell 对象 (PSCustomObjects) 针对流式处理进行了优化,因为它包含其属性的所有类型信息。这使得这些 PowerShell 对象很重,不太适合将它们存储在(大)集合中。
特定于您自己的功能,它使您的 input processing methods (the Start
, Process
and End
block structure) pointless which is especially developed to Process
each specific object in the pipeline. If you collect all your objects in an array before passing it to your BuildArray
function, you might as well just use the End
block (or leave all the input blocks which is similar to just an End
block) where the automated $Input
variable 将 管道中提供的所有对象 保存在一个数组中:
Function BuildArray {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]$data
)
Process { Write-Host 'Process:' $Input }
}
1,2,3 | BuildArray
Process: 1
Process: 2
Process: 3
Function BuildArray {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]$data
)
End { Write-Host 'End:' $Input } # or just: Write-Host $Input
}
1,2,3 | BuildArray
End: 1 2 3
另外:
- 尽量避免使用递增赋值运算符 (+=) 创建一个
collection(或字符串)原样
指数昂贵。
- 如果您确实要使用它,您应该正确地初始化
$dat = ''
值,否则您可能会以从其中一个父函数继承的意外副本开始。
我有以下功能:
Function Refine{
[CmdletBinding()]
param (
[parameter(ValueFromPipeline = $true)]
$data
)
begin {}
process {
For ($i=0; $i -le $data.count; $i++){
if ($data[$i] -match 'nmap scan report' -and $data[$i+1] -match 'host is up' ) {
$dat += $data[$i] + "`n"
$counter=($i+4)
while ($data[$counter] -match '^[0-9]') {
$dat += $data[$counter] + "`n"
$counter++
}
}
}
}
end {
if ($dat){#See that its not empty
return $dat.Split([Environment]::NewLine)
}
}
}
$file1 = gc c:\test.txt
,gc ($file1) | Refine
我必须使用一元运算符进行管道传输,因为我希望将整个对象一次性传输到优化函数。
例如,输出是这样的: 1.1.1.1 的 Nmap 扫描报告 113/tcp 关闭标识 443/tcp 打开 ssl/http Fortinet SSL VPN 2.2.2.2 的 Nmap 扫描报告 21/tcp 过滤 ftp 22/tcp 过滤 ssh
我现在想使用另一个函数,它接受这个并从文本创建对象:
Function BuildArray{
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]
$data
)
Begin {}
Process {
$NMAPS=@()
$nmap=@()
$ports=@()
For ($i=0; $i -lt $data.count; $i++){
If ($data[$i] -match 'nmap scan report') {
$ip = ($data[$i] | Select-String -Pattern "\d{1,3}(\.\d{1,3}){3}" -AllMatches).Matches.Value
$k=$i
If ($data[($i+1)] -notmatch 'nmap scan report' -and $i -le $data.count){
DO{
$ports+=$data[$i+1]
$i++
}
While ($data[$i+1] -notmatch 'nmap scan report' -and $i -le $data.count)
$nmap = @{IP = "$ip"; ports=@($ports)}
$NMAPS+=$nmap
$nmap=@()
$ports=@()
$i = $k
}
}
}
}
End {
$NMAPS
}
}
我的问题又来了——我希望管道中的数据作为一个整体传递给 BuildArray 函数。但我不能使用一元运算符,因为我收到一条错误消息,说我只能在管道的开头使用它,
,(gc $file1 ) | ,(refine) | BuildArray #No good
如何将管道中的第二个对象作为一个整体一次性传递给第三个对象?
恕我直言,您对 PowerShell pipeline. Cmdlets should implement for the Middle of a Pipeline 的一般概念并不正确,这意味着每个 cmdlet 都应该处理每个项目 a.s.a.p。 将其流到下一个cmdlet,最终将其从内存中释放。
PowerShell 对象 (PSCustomObjects) 针对流式处理进行了优化,因为它包含其属性的所有类型信息。这使得这些 PowerShell 对象很重,不太适合将它们存储在(大)集合中。
特定于您自己的功能,它使您的 input processing methods (the Start
, Process
and End
block structure) pointless which is especially developed to Process
each specific object in the pipeline. If you collect all your objects in an array before passing it to your BuildArray
function, you might as well just use the End
block (or leave all the input blocks which is similar to just an End
block) where the automated $Input
variable 将 管道中提供的所有对象 保存在一个数组中:
Function BuildArray {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]$data
)
Process { Write-Host 'Process:' $Input }
}
1,2,3 | BuildArray
Process: 1
Process: 2
Process: 3
Function BuildArray {
[CmdletBinding()]
Param(
[Parameter(ValueFromPipeline = $true)]$data
)
End { Write-Host 'End:' $Input } # or just: Write-Host $Input
}
1,2,3 | BuildArray
End: 1 2 3
另外:
- 尽量避免使用递增赋值运算符 (+=) 创建一个
collection(或字符串)原样
指数昂贵。
- 如果您确实要使用它,您应该正确地初始化
$dat = ''
值,否则您可能会以从其中一个父函数继承的意外副本开始。
- 如果您确实要使用它,您应该正确地初始化